﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.Data.SqlClient;
using System.Xml.Serialization;
using System.IO;

namespace XEvents.Library.Internal
{
    [Serializable]
    public class MetaData : XEventBase
    {
        internal MetaData(SqlServer server)
            : base(server)
        {
            BuildMetaData();
        }

        private MetaData(): base(null)
        { }

        public System.Xml.XmlDocument GetXml()
        {
            return Utilities.GetSerializedXml(typeof(MetaData), Server.MetaData);
        }

        #region Private Members

        internal List<dm_xe_package> packages;
        internal List<dm_xe_object> objects;
        internal List<dm_xe_object_column> object_columns;
        internal List<dm_xe_map_values> map_values;

        #endregion

        #region Private Methods
        private void BuildMetaData()
        {
            packages = new List<dm_xe_package>();
            objects = new List<dm_xe_object>();
            object_columns = new List<dm_xe_object_column>();
            map_values = new List<dm_xe_map_values>();

            SqlDataReader dr = Server.ServerConnection.ExecuteReader(SqlCommandStrings.MetaData);

            dm_xe_package p;
            dm_xe_object o;
            dm_xe_object_column c;
            dm_xe_map_values mv;

            while (dr.Read())
            {
                p = new dm_xe_package(dr);
                this.packages.Add(p);
            }
            dr.NextResult();
            while (dr.Read())
            {
                o = new dm_xe_object(dr);
                this.objects.Add(o);
            }
            dr.NextResult();
            while (dr.Read())
            {
                c = new dm_xe_object_column(dr);
                this.object_columns.Add(c);
            }
            dr.NextResult();
            while (dr.Read())
            {
                mv = new dm_xe_map_values(dr);
                this.map_values.Add(mv);
            }

            dr.Close();

        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Extended Events Packages
        /// </summary>
        public PackageCollection Packages
        {
            get
            {
                PackageCollection pc = new PackageCollection((from pack in packages
                                                              select new Package(pack, this.Server)).OrderBy(s => s.Name));
                return pc;
            }
        }

        /// <summary>
        /// Extended Events Events
        /// </summary>
        public IEnumerable<Event> Events
        {
            get
            {
                return (from o in objects
                        where o.object_type == "event"
                        && o.capabilities != 1
                        select new Event(o, this.Server)).OrderBy(s => s.name);
            }
        }

        /// <summary>
        /// Extended Events Actions
        /// </summary>
        public IEnumerable<Action> Actions
        {
            get
            {
                return (from a in objects
                        where a.object_type == "action"
                        select new Action(a, this.Server)).OrderBy(s => s.name);
            }
        }

        /// <summary>
        /// Extended Events Targets
        /// </summary>
        public IEnumerable<Target> Targets
        {
            get
            {
                return (from o in objects
                        where o.object_type == "target"
                        select new Target(o, this.Server)).OrderBy(s => s.name);
            }
        }

        /// <summary>
        /// Extended Event Predicates
        /// </summary>
        public IEnumerable<Predicate> Predicates
        {
            get
            {
                return (from o in objects
                        where o.object_type == "pred_source" || o.object_type == "pred_compare"
                        select new Predicate(o, this.Server)).OrderBy(s => s.name);
            }
        }

        /// <summary>
        /// Extended Events Types
        /// </summary>
        public IEnumerable<Type> Types
        {
            get
            {
                return (from o in objects
                        where o.object_type == "type"
                        select new Type(o, this.Server)).OrderBy(s => s.name);
            }
        }

        /// <summary>
        /// Extended Events Maps
        /// </summary>
        public IEnumerable<Map> Maps
        {
            get
            {
                return (from o in objects
                        where o.object_type == "map"
                        select new Map(o, this.Server)).OrderBy(s => s.name);
            }
        }

        #endregion

    }
}
